package client;

import com.google.gwt.user.client.ui.RichTextArea;

/**
 * Created by IntelliJ IDEA.
 * User: Wouter Wendelen
 * Date: 12-okt-2007
 * Time: 12:41:11
 */
public class CssHelper {

    public static String toCss(RichTextArea area, String className) {
        return replace(area, "span", "class", className, "");
    }

    public static String toLink(RichTextArea area, String url, String extra) {
        return replace(area, "a", "href", url, extra);
    }

    public static String insert(RichTextArea area, String toInsert) {
        preInsert(area);
        return postInsert(area, toInsert);
    }

    public static String postInsert(RichTextArea area, String toInsert) {
        return replace(area.getHTML(), "img src=\"http://dummy", toInsert);
    }

    public static void preInsert(RichTextArea area) {
        area.getExtendedFormatter().insertImage("http://dummy");
    }

    private static String replace(RichTextArea area, String tag, String attributeName, String attributeValue, String extra) {
        // try selection
        area.getBasicFormatter().setFontSize(RichTextArea.FontSize.X_SMALL);
        return replace(area.getHTML(), "font", tag, attributeName, attributeValue, extra);
    }


    public static String replace(String html, String replaceTag, String tag, String attributeName, String attributeValue, String extra) {
        String lowerReplaceTag = replaceTag.toLowerCase();
        String lowerAttributeValue = attributeValue.toLowerCase();
        int replaceTagStartStartPos = html.toLowerCase().indexOf("<" + lowerReplaceTag);
        while (replaceTagStartStartPos >= 0) {

            boolean empty = "".equals(lowerAttributeValue);
            String includeTagStart = empty ? "" : "<" + tag + " " + attributeName + "=\"" + attributeValue + "\"" + (extra == null ? "" : " " + extra) + ">";

            int replaceTagStartEndPos = html.indexOf('>', replaceTagStartStartPos);

            String htmlBeforeSelection = html.substring(0, replaceTagStartStartPos);
            String replaceTagEnd = getEndTag(html, replaceTagStartStartPos, tag);

            int replaceTagEndStartPos = html.indexOf(replaceTagEnd, replaceTagStartEndPos);
            String selection = html.substring(replaceTagStartEndPos + 1, replaceTagEndStartPos);
            String htmlAfterSelection = html.substring(replaceTagEndStartPos + replaceTagEnd.length());

            String startSelection = includeTagStart;
            String endSelection = empty ? "" : "</" + tag + ">";

            boolean doEnd = true;

            // do htmlBeforeSelection
            Info startInfo = doStart(htmlBeforeSelection, tag);
            if (!isEmpty(startInfo.getOpen())) {
                // there is an open span tag, with content in between
                if (isEqualTag(startInfo.getOpen(), attributeName, lowerAttributeValue)) {
                    // equals to insert tag
                    startSelection = "";
                    endSelection = "";
                    doEnd = false;
                }
                else {
                    htmlBeforeSelection = htmlBeforeSelection + getEndTag(startInfo.getOpen(), 0, null);
                    htmlAfterSelection = startInfo.getOpen() + htmlAfterSelection;
                }
            }
            else {
                // no open span tag across selection
                if (isEmpty(startInfo.getHtmlAfterSplitTag()) && isEqualTag(startInfo.getSplitTag(), attributeName, lowerAttributeValue)) {
                    htmlBeforeSelection = startInfo.getHtmlBeforeSplitTag() + includeTagStart + startInfo.getHtmlBetweenSplitTag() + startInfo.getHtmlAfterSplitTag();
                    startSelection = "";
                }
                else {
                    String endT = "</" + tag + ">";
                    if (isEmpty(startInfo.getSplitTag())) {
                        endT = "";
                    }
                    htmlBeforeSelection = startInfo.getHtmlBeforeSplitTag() + noNull(startInfo.getSplitTag()) + noNull(startInfo.getHtmlBetweenSplitTag()) + endT + noNull(startInfo.getHtmlAfterSplitTag());
                }
                htmlAfterSelection = noNull(startInfo.getWasOpen()) + htmlAfterSelection;
            }

            // do htmlAfterSelection
            if (doEnd) {
                String[] endSplit = splitEndStart(htmlAfterSelection, tag);
                if (endSplit.length > 1) {
                    String aTag = endSplit[1];
                    if (isEmpty(endSplit[0]) && isEqualTag(aTag, attributeName, lowerAttributeValue)) {
                        endSelection = "";
                        aTag = "";
                    }
                    htmlAfterSelection = endSplit[0] + aTag + endSplit[2] + endSplit[3] + endSplit[4];
                }
                else {
                    htmlAfterSelection = endSplit[0];
                }
            }
            // do selection - strip all same tags
            selection = stripTags(selection, tag);
            html = htmlBeforeSelection + startSelection + selection + endSelection + htmlAfterSelection;

            replaceTagStartStartPos = html.toLowerCase().indexOf("<" + lowerReplaceTag);
        }
        return html;
    }

    public static String replace(String html, String oldTagStart, String newValue) {
        int replaceStartPos = html.toLowerCase().indexOf("<" + oldTagStart);

        if (replaceStartPos >= 0) {
            int replaceEndPos = html.indexOf('>', replaceStartPos);
            String htmlBeforeReplace = html.substring(0, replaceStartPos);
            String htmlAfterReplace = html.substring(replaceEndPos+1);
            html = htmlBeforeReplace + newValue + htmlAfterReplace;
        }
        return html;
    }

    private static String noNull(String str) {
        return str == null ? "" : str;
    }

    private static boolean isEqualTag(String tag, String attributeName, String attributeValue) {
        String lowerTag = tag == null ? "" : tag.toLowerCase();
        return !"".equals(attributeValue) && (lowerTag.indexOf(attributeName + "=\"" + attributeValue + "\"") > 0 || lowerTag.indexOf(attributeName + "=" + attributeValue) > 0);
    }

    private static Info doStart(String start, String splitTtag) {
        return splitStartEnd(new Info(start), splitTtag);
    }

    private static Info splitStartEnd(Info info, String splitTtagName) {
        String lower = info.getHtmlBeforeSplitTag().toLowerCase();
        int currentSplitTagStartPos = lower.lastIndexOf("<" + splitTtagName);
        if (currentSplitTagStartPos >= 0) {
            String htmlBeforeSplitTag = info.getHtmlBeforeSplitTag().substring(0, currentSplitTagStartPos);
            String currentSplitTag = getStartTag(info.getHtmlBeforeSplitTag(), currentSplitTagStartPos);
            int currentSplitTagEndPos = lower.indexOf("</" + splitTtagName + ">", currentSplitTagStartPos);
            if (currentSplitTagEndPos >= 0) {
                String htmlBetweenSplitTag = info.getHtmlBeforeSplitTag().substring(currentSplitTagStartPos + currentSplitTag.length(), currentSplitTagEndPos);
                String htmlAfterSplitTag = info.getHtmlBeforeSplitTag().substring(currentSplitTagEndPos + splitTtagName.length() + 3);
                if (isEmpty(htmlBetweenSplitTag)) {
                    info.setHtmlBeforeSplitTag(htmlBeforeSplitTag + htmlBetweenSplitTag + htmlAfterSplitTag);
                    return splitStartEnd(info, splitTtagName);
                }
                info.setHtmlBeforeSplitTag(htmlBeforeSplitTag);
                info.setSplitTag(currentSplitTag);
                info.setHtmlBetweenSplitTag(htmlBetweenSplitTag);
                info.setHtmlAfterSplitTag(htmlAfterSplitTag);
                return info;
            }
            String htmlBetweenSplitTag = info.getHtmlBeforeSplitTag().substring(currentSplitTagStartPos + currentSplitTag.length());
            if (isEmpty(htmlBetweenSplitTag)) {
                info.setHtmlBeforeSplitTag(htmlBeforeSplitTag + htmlBetweenSplitTag);
                info = splitStartEnd(info, splitTtagName);
                info.setWasOpen(currentSplitTag);
                return info;
            }
            info.setHtmlBeforeSplitTag(htmlBeforeSplitTag);
            info.setHtmlBetweenSplitTag(htmlBetweenSplitTag);
            info.setOpen(currentSplitTag);
        }
        return info;
    }

    private static boolean isEmpty(String str) {
        return str == null || "".equals(str.trim());
    }

    private static String[] splitEndStart(String html, String splitTtag) {
        String lower = html.toLowerCase();
        int splitTagStartStartPos = lower.indexOf("<" + splitTtag);
        if (splitTagStartStartPos >= 0) {
            String htmlBeforeSplitTag = html.substring(0, splitTagStartStartPos);
            String splitTagStart = getStartTag(html, splitTagStartStartPos);
            int splitTagEndStartPos = lower.indexOf("</" + splitTtag + ">", splitTagStartStartPos);
            String splitTagEnd = html.substring(splitTagEndStartPos, splitTagEndStartPos + splitTtag.length() + 3);
            String htmlBetweenSplitTag = html.substring(splitTagStartStartPos + splitTagStart.length(), splitTagEndStartPos);
            String htmlAfterSplitTag = html.substring(splitTagEndStartPos + splitTtag.length() + 3);
            if (isEmpty(htmlBetweenSplitTag)) {
                return splitEndStart(htmlBeforeSplitTag + htmlBetweenSplitTag + htmlAfterSplitTag, splitTtag);
            }
            return new String[]{
                    htmlBeforeSplitTag,
                    splitTagStart,
                    htmlBetweenSplitTag,
                    splitTagEnd,
                    htmlAfterSplitTag};
        }
        return new String[]{html};
    }

    private static String getEndTag(String html, int startTagPos, String forbiddenTag) {
        String tagName = html.substring(startTagPos + 1, html.indexOf(' ', startTagPos));
        if (tagName.equals(forbiddenTag)) {
            throw new RuntimeException("tag to replace can not be the same as tag to include");
        }
        return "</" + tagName + ">";
    }

    private static String getStartTag(String html, int startTagPos) {
        return html.substring(startTagPos, html.indexOf('>', startTagPos) + 1);
    }

    private static String stripTags(String str, String tag) {
        String lower = str.toLowerCase();
        int startIndex = lower.indexOf("<" + tag);
        while (startIndex >= 0) {
            int endStart = lower.indexOf('>', startIndex);
            // there should be a closing tag
            int closeIndex = lower.indexOf("</" + tag + ">");
            str = str.substring(0, startIndex) + str.substring(endStart + 1, closeIndex) + str.substring(closeIndex + tag.length() + 3);
            lower = str.toLowerCase();
            startIndex = lower.indexOf("<" + tag);
        }
        return str;
    }
}